﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;

namespace DDOS
{
    public class ScreenManager
    {
        #region Fields/Properties
        private static ScreenManager managerReference = null;
        private ScreenLayer transitionScreen = null;
        private Screen nextScreen = null;
        private bool popFlag = false;
        private bool inTransition = false;

        private Camera2D cam;
        public Camera2D Camera
        {
            get { return cam; }
        }

        public static ScreenManager Instance
        {
            get
            {
                return managerReference;
            }
        }
        #endregion

        private Screen currentScreen;
        /// <summary>
        /// Represents the current screen being updated and drawn by the ScreenManager.
        /// </summary>
        public Screen CurrentScreen 
        {
            get
            {
                return currentScreen;
            }
        }

        private Rectangle actualScreenBounds;
        /// <summary>
        /// Represents the actual bounds of the television screen as a Rectangle.
        /// </summary>
        public Rectangle ActualScreenBounds 
        {
            get
            {
                return actualScreenBounds;
            }
        }

        private Rectangle screenBounds;
        /// <summary>
        /// Represents the bounds of the television screen the game will use as a Rectangle.
        /// </summary>
        public Rectangle ScreenBounds
        {
            get
            {
                return GraphicsDevice.Viewport.TitleSafeArea;
            }
        }

        private GraphicsDevice graphics;
        /// <summary>
        /// A universally accessible GraphicsDevice object, used by all components of the game.
        /// </summary>
        public GraphicsDevice GraphicsDevice
        {
            get
            {
                return graphics;
            }
        }

        private SpriteBatch spriteBatch;
        /// <summary>
        /// A universally accessible SpriteBatch created from the ScreenManager's GraphicsDevice reference.
        /// </summary>
        public SpriteBatch CurrentSpriteBatch
        {
            get
            {
                return spriteBatch;
            }
        }

        private Transition curTransType;
        public Transition TransitionType { get { return curTransType; } set { curTransType = value; } }

        public Game game;
        
        #region Private constructor
        private ScreenManager()
        {
        }
        #endregion

        /// <summary>
        /// Initializes the static ScreenManager instance.
        /// </summary>
        /// <param name="actualScreen">The actual bounds of the television screen</param>
        /// <param name="screen">The assumed bounds of the television screen</param>
        /// <param name="graphicsDev">A universally accessible GraphicsDevice object used for drawing</param>
        public static void Initialize(Rectangle actualScreen, Rectangle screen, GraphicsDevice graphicsDev, Game g)
        {
            
            managerReference = new ScreenManager();
            managerReference.game = g;
            managerReference.actualScreenBounds = actualScreen;
            managerReference.screenBounds = screen;
            managerReference.graphics = graphicsDev;
            managerReference.spriteBatch = new SpriteBatch(graphicsDev);

            managerReference.cam = new Camera2D(new Vector2(screen.X / 2, screen.Y / 2), 1.0f, 0.0f);
        
        }


        /// <summary>
        /// Updates the CurrentScreen and/or transition screen layer.
        /// </summary>
        /// <param name="gt"></param>
        public void Update(GameTime gt)
        {
            if (popFlag)
            {
                popFlag = false;
                CurrentScreen.PopLayer(1);
            }
            CurrentScreen.Update(gt);
        }

        /// <summary>
        /// Draws the CurrentScreen and/or transition screen layer.
        /// </summary>
        /// <param name="sb"></param>
        public void Draw()
        {
            Vector2 resolution = new Vector2(screenBounds.X, screenBounds.Y);
            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null, cam.GetTransform(resolution));

            CurrentScreen.Draw();

            spriteBatch.End();
        }

        /// <summary>
        /// Triggers the transition screen layer and begins loading a new Screen.
        /// </summary>
        /// <param name="newScreen"></param>
        public void LoadScreen(Screen newScreen)
        {
            if (CurrentScreen == null)
            {
                currentScreen = newScreen;
                CurrentScreen.OnLoad();
            }
            else
            {
                if (!inTransition)
                {
                    inTransition = true;
                    nextScreen = newScreen;
                    transitionScreen = new TransitionScreenLayer(20);
                    CurrentScreen.PushLayer(transitionScreen);
                }
            }
        }

        

        

        

        /// <summary>
        /// Called when the transition screen reaches its halfway point (preferably taking up the entire screen.
        /// At this point, the old Screen is replaced by the new Screen (the one passed to the last call to LoadScreen).
        /// </summary>
        public void TransitionHalfwayPoint()
        {
                CurrentScreen.OnExit();
                nextScreen.PushLayer(transitionScreen);
                
                currentScreen = nextScreen;
                CurrentScreen.OnLoad();
        }
        

        /// <summary>
        /// Called when the transition screen layer is entirely finished.  Simply removes the transition screen layer.
        /// </summary>
        public void TransitionEnded()
        {
            inTransition = false;
            popFlag = true;
        }
    }
}